package io.github.jsp.tranvolume.service;

import io.github.jsp.tranvolume.mapper.TranVolumeProvinceMapper;
import io.github.jsp.tranvolume.mapper.TranVolumeTotalMapper;
import io.github.jsp.tranvolume.mapper.TranFailCodeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 交易量监控服务
 */
@Service
public class TranVolumeMonitorService {

    @Autowired
    private TranVolumeProvinceMapper provinceMapper;
    
    @Autowired
    private TranVolumeTotalMapper totalMapper;
    
    @Autowired
    private TranFailCodeMapper failCodeMapper;

    private final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm");
    
    private final Map<String, String> PROVINCE_NAMES = new HashMap<String, String>() {{
        put("11", "北京");
        put("12", "天津"); 
        put("13", "河北");
        put("14", "山西");
        put("15", "内蒙古");
        put("21", "辽宁");
        put("22", "吉林");
        put("23", "黑龙江");
        put("31", "上海");
        put("32", "江苏");
        put("33", "浙江");
        put("34", "安徽");
        put("35", "福建");
        put("36", "江西");
        put("37", "山东");
    }};
    
    private final Map<String, String> CENTER_NAMES = new HashMap<String, String>() {{
        put("hf", "合肥中心");
        put("yz", "亦庄中心");
        put("lf", "廊坊中心");
    }};

    /**
     * 获取省份交易量环比数据
     */
    public Map<String, Object> getProvinceCompareData(String provCode, String servicePlat, String chelCode, Integer timeRange) {
        LocalDateTime endTime = LocalDateTime.now();
        LocalDateTime startTime = endTime.minusDays(timeRange != null ? timeRange : 7);
        
        // TODO: 根据 servicePlat 和 chelCode 过滤数据
        List<Map<String, Object>> data = provCode != null ? 
            Collections.singletonList(getProvinceDataByCode(provCode, startTime, endTime)) :
            getAllProvinceData(startTime, endTime);
            
        Map<String, Object> result = new HashMap<>();
        result.put("provinces", data);
        result.put("updateTime", endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        return result;
    }
    
    private Map<String, Object> getProvinceDataByCode(String provCode, LocalDateTime startTime, LocalDateTime endTime) {
        Map<String, Object> provinceData = new HashMap<>();
        provinceData.put("provCode", provCode);
        provinceData.put("provName", PROVINCE_NAMES.getOrDefault(provCode, "未知省份"));
        
        List<Map<String, Object>> currentData = generateTimeSeriesData(startTime, endTime, 800, 1200);
        List<Map<String, Object>> historyData = generateTimeSeriesData(startTime.minusDays(7), endTime.minusDays(7), 700, 1100);
        
        provinceData.put("currentData", currentData);
        provinceData.put("historyData", historyData);
        provinceData.put("compareRate", calculateCompareRate(currentData, historyData));
        
        return provinceData;
    }
    
    private List<Map<String, Object>> getAllProvinceData(LocalDateTime startTime, LocalDateTime endTime) {
        List<String> provinces = Arrays.asList("11", "12", "13", "14", "15");
        return provinces.stream()
            .map(prov -> getProvinceDataByCode(prov, startTime, endTime))
            .collect(Collectors.toList());
    }

    /**
     * 获取中心交易量实时监控数据
     */
    public Map<String, Object> getCenterRealtimeData(String center, String provCode, String servicePlat, String chelCode, Integer timeRange) {
        LocalDateTime endTime = LocalDateTime.now();
        LocalDateTime startTime = endTime.minusHours(timeRange != null ? timeRange : 6);
        
        // TODO: 根据 provCode、servicePlat 和 chelCode 过滤数据
        if (center != null) {
            Map<String, Object> centerData = getCenterDataByCode(center, startTime, endTime);
            Map<String, Object> result = new HashMap<>();
            result.put("center", centerData);
            result.put("updateTime", endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            return result;
        } else {
            List<String> centers = Arrays.asList("hf", "yz", "lf");
            List<Map<String, Object>> centersData = centers.stream()
                .map(c -> getCenterDataByCode(c, startTime, endTime))
                .collect(Collectors.toList());
                
            Map<String, Object> result = new HashMap<>();
            result.put("centers", centersData);
            result.put("updateTime", endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            return result;
        }
    }
    
    private Map<String, Object> getCenterDataByCode(String center, LocalDateTime startTime, LocalDateTime endTime) {
        Map<String, Object> centerData = new HashMap<>();
        centerData.put("center", center);
        centerData.put("centerName", CENTER_NAMES.getOrDefault(center, "未知中心"));
        
        int baseVolume = "hf".equals(center) ? 15000 : ("yz".equals(center) ? 12000 : 10000);
        List<Map<String, Object>> volumeData = generateTimeSeriesData(startTime, endTime, baseVolume - 2000, baseVolume + 2000);
        List<Map<String, Object>> successRateData = generateSuccessRateData(startTime, endTime);
        
        centerData.put("volumeData", volumeData);
        centerData.put("successRateData", successRateData);
        centerData.put("currentVolume", baseVolume + new Random().nextInt(4000) - 2000);
        centerData.put("currentSuccessRate", 98.5 + new Random().nextDouble() * 1.5);
        
        return centerData;
    }

    /**
     * 获取失败响应码趋势数据
     */
    public Map<String, Object> getFailCodeTrendData(String center, String provCode, String servicePlat, String chelCode, Integer timeRange, Integer limit) {
        LocalDateTime endTime = LocalDateTime.now();
        LocalDateTime startTime = endTime.minusHours(timeRange != null ? timeRange : 6);
        
        // TODO: 根据 center、provCode、servicePlat 和 chelCode 过滤数据
        List<Map<String, Object>> failCodes = generateFailCodeData(limit != null ? limit : 10);
        List<Map<String, Object>> timeData = generateTimeData(startTime, endTime);
        
        Map<String, Object> result = new HashMap<>();
        result.put("failCodes", failCodes);
        result.put("timeData", timeData);
        result.put("updateTime", endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        return result;
    }
    
    private List<Map<String, Object>> generateTimeSeriesData(LocalDateTime startTime, LocalDateTime endTime, int minValue, int maxValue) {
        List<Map<String, Object>> data = new ArrayList<>();
        Random random = new Random();
        
        LocalDateTime current = startTime;
        while (current.isBefore(endTime)) {
            Map<String, Object> point = new HashMap<>();
            point.put("time", current.format(TIME_FORMATTER));
            point.put("value", minValue + random.nextInt(maxValue - minValue));
            point.put("successRate", 96.0 + random.nextDouble() * 4.0);
            data.add(point);
            
            current = current.plusMinutes(5);
        }
        
        return data;
    }
    
    private List<Map<String, Object>> generateSuccessRateData(LocalDateTime startTime, LocalDateTime endTime) {
        List<Map<String, Object>> data = new ArrayList<>();
        Random random = new Random();
        
        LocalDateTime current = startTime;
        while (current.isBefore(endTime)) {
            Map<String, Object> point = new HashMap<>();
            point.put("time", current.format(TIME_FORMATTER));
            point.put("value", 96.0 + random.nextDouble() * 4.0);
            data.add(point);
            
            current = current.plusMinutes(1);
        }
        
        return data;
    }
    
    private List<Map<String, Object>> generateFailCodeData(int limit) {
        Map<String, String> failCodeDesc = new HashMap<String, String>() {{
            put("Z00000", "系统异常");
            put("110022", "网络超时");
            put("999999", "未知错误");
            put("888888", "数据库连接失败");
            put("777777", "服务不可用");
        }};
        
        List<Map<String, Object>> failCodes = new ArrayList<>();
        Random random = new Random();
        
        for (Map.Entry<String, String> entry : failCodeDesc.entrySet()) {
            Map<String, Object> failCode = new HashMap<>();
            failCode.put("retCode", entry.getKey());
            failCode.put("retDesc", entry.getValue());
            failCode.put("failCount", 50 + random.nextInt(200));
            failCode.put("failRate", 0.1 + random.nextDouble() * 0.5);
            failCodes.add(failCode);
            
            if (failCodes.size() >= limit) break;
        }
        
        return failCodes;
    }
    
    private double calculateCompareRate(List<Map<String, Object>> currentData, List<Map<String, Object>> historyData) {
        if (currentData.isEmpty() || historyData.isEmpty()) return 0.0;
        
        long currentSum = currentData.stream().mapToLong(d -> ((Integer) d.get("value")).longValue()).sum();
        long historySum = historyData.stream().mapToLong(d -> ((Integer) d.get("value")).longValue()).sum();
        
        if (historySum == 0) return 0.0;
        return ((double) (currentSum - historySum) / historySum) * 100;
    }
    
    private List<Map<String, Object>> generateTimeData(LocalDateTime startTime, LocalDateTime endTime) {
        List<Map<String, Object>> data = new ArrayList<>();
        
        LocalDateTime current = startTime;
        while (current.isBefore(endTime)) {
            Map<String, Object> point = new HashMap<>();
            point.put("time", current.format(TIME_FORMATTER));
            data.add(point);
            
            current = current.plusHours(1); // 每小时一个数据点
        }
        
        return data;
    }
}